#pragma once
#ifndef __TESTBOARD__H__
#define __TESTBOARD__H__

#include "ATTest.h"

static const UInt32 BOARD_ROW = 9;
static const UInt32 BOARD_COL = 9;

class BoardTestCase : public TestCase
{
public:
	BoardTestCase(const Char* pszName) : TestCase(pszName)
	{
		Add(NEW_TEST(BoardTestCase::TestMakeBlockSet));
		Add(NEW_TEST(BoardTestCase::TestRowBlock));
		Add(NEW_TEST(BoardTestCase::TestColBlock));
		Add(NEW_TEST(BoardTestCase::TestSquareBlock));
		Add(NEW_TEST(BoardTestCase::TestGCD));
		Add(NEW_TEST(BoardTestCase::TestSquareSize));
		Add(NEW_TEST(BoardTestCase::TestLastestCD));
		Add(NEW_TEST(BoardTestCase::TestMakeSquareBlock));
		Add(NEW_TEST(BoardTestCase::TestMakeSquareBlock2));
	}

	virtual Bool SetUp()
	{
		return aBoard_.CreateCell(BOARD_COL, BOARD_ROW);
	}

	virtual Bool TearDown()
	{
		return aBoard_.DestroyCell();
	}

	int TestRowBlock()
	{
		ATSudokuEngine::Block aBlock;
		ATASSERT(aBoard_.Row(0, aBlock));
		ATASSERT(aBlock.Size() == BOARD_ROW);
		
		return 0;
	}

	int TestColBlock()
	{
		ATSudokuEngine::Block aBlock;
		ATASSERT(aBoard_.Col(0, aBlock));
		ATASSERT(aBlock.Size() == BOARD_COL);
		
		return 0;
	}

	int TestSquareBlock()
	{
		ATSudokuEngine::Block aBlock;
		ATASSERT(aBoard_.Square(0, aBlock));
		ATASSERT(aBlock.Size() == BOARD_COL);
		
		return 0;
	}

	int TestMakeBlockSet()
	{
		ATSudokuEngine::BlockSet aBlockSet;
		ATASSERT(aBoard_.Blocks(0, aBlockSet));
		
		ATASSERT(aBlockSet.Value(1));

		return 0;
	}

	int TestGCD()
	{
		ATASSERT(ATSudokuEngine::Board::_GCD(27, 18) == 9);
		ATASSERT(ATSudokuEngine::Board::_GCD(25, 15) == 5);
		ATASSERT(ATSudokuEngine::Board::_GCD(15, 10) == 5);
		ATASSERT(ATSudokuEngine::Board::_GCD(30, 24) == 6);
		return 0;
	}

	int TestLastestCD()
	{
		UInt32 nCol = 0;
		UInt32 nRow = 0;

		ATSudokuEngine::Board::_LastestCD(32, nCol, nRow);
		ATASSERT(nCol == 8);
		ATASSERT(nRow == 4);

		ATSudokuEngine::Board::_LastestCD(15, nCol, nRow);
		ATASSERT(nCol == 5);
		ATASSERT(nRow == 3);

		ATSudokuEngine::Board::_LastestCD(20, nCol, nRow);
		ATASSERT(nCol == 5);
		ATASSERT(nRow == 4);

		ATSudokuEngine::Board::_LastestCD(28, nCol, nRow);
		ATASSERT(nCol == 7);
		ATASSERT(nRow == 4);

		ATSudokuEngine::Board::_LastestCD(9, nCol, nRow);
		ATASSERT(nCol == 3);
		ATASSERT(nRow == 3);

		ATSudokuEngine::Board::_LastestCD(25, nCol, nRow);
		ATASSERT(nCol == 5);
		ATASSERT(nRow == 5);

		ATSudokuEngine::Board::_LastestCD(81, nCol, nRow);
		ATASSERT(nCol == 9);
		ATASSERT(nRow == 9);
		return 0;
	}

	int TestSquareSize()
	{
		UInt32 nSquareCol = 0;
		UInt32 nSquareRow = 0;

		ATSudokuEngine::Board::_SquareSize(9, 9, nSquareCol, nSquareRow);
		ATASSERT(nSquareCol == 3);
		ATASSERT(nSquareRow == 3);
		
		ATSudokuEngine::Board::_SquareSize(25, 25, nSquareCol, nSquareRow);
		ATASSERT(nSquareCol == 5);
		ATASSERT(nSquareRow == 5);
		
		ATSudokuEngine::Board::_SquareSize(15, 15, nSquareCol, nSquareRow);
		ATASSERT(nSquareCol == 5);
		ATASSERT(nSquareRow == 3);

		return 0;
	}

	int TestMakeSquareBlock()
	{
		ATSudokuEngine::BlockSet aBlockSet3;
		ATASSERT(aBoard_.Blocks(3, aBlockSet3));
		ATASSERT(aBlockSet3.Value(3));

		ATSudokuEngine::BlockSet aBlockSet4;
		ATASSERT(aBoard_.Blocks(4, aBlockSet4));
		ATASSERT(aBlockSet4.Value(4));

		ATSudokuEngine::BlockSet aBlockSet5;
		ATASSERT(aBoard_.Blocks(5, aBlockSet5));
		ATASSERT(aBlockSet5.Value(5));

		ATSudokuEngine::Block aSquareBlock2;
		ATASSERT(aBoard_.Square(3, aSquareBlock2));
		const ATSudokuEngine::Cell* pCell3Clone = aSquareBlock2.At(0);
		ATASSERT(3 == pCell3Clone->Value());

		const ATSudokuEngine::Cell* pCell4Clone = aSquareBlock2.At(1);
		ATASSERT(4 == pCell4Clone->Value());

		const ATSudokuEngine::Cell* pCell5Clone = aSquareBlock2.At(2);
		ATASSERT(5 == pCell5Clone->Value());

		return 0;
	}

	int TestMakeSquareBlock2()
	{
		ATSudokuEngine::BlockSet aBlockSet30;
		ATASSERT(aBoard_.Blocks(30, aBlockSet30));
		ATASSERT(aBlockSet30.Value(3));

		ATSudokuEngine::BlockSet aBlockSet40;
		ATASSERT(aBoard_.Blocks(40, aBlockSet40));
		ATASSERT(aBlockSet40.Value(4));

		ATSudokuEngine::BlockSet aBlockSet50;
		ATASSERT(aBoard_.Blocks(50, aBlockSet50));
		ATASSERT(aBlockSet50.Value(5));

		ATSudokuEngine::Block aSquareBlock;
		ATASSERT(aBoard_.Square(30, aSquareBlock));

		const ATSudokuEngine::Cell* pCell30Clone = aSquareBlock.At(0);
		ATASSERT(3 == pCell30Clone->Value());

		const ATSudokuEngine::Cell* pCell40Clone = aSquareBlock.At(4);
		ATASSERT(4 == pCell40Clone->Value());

		const ATSudokuEngine::Cell* pCell50Clone = aSquareBlock.At(8);
		ATASSERT(5 == pCell50Clone->Value());

		return 0;
	}

protected:
	ATSudokuEngine::Board aBoard_;
};

#endif